package com.hyts.jgit.handler;

import com.hyts.jgit.base.model.ResultModel;
import com.hyts.jgit.base.spi.RemoteBaseSpi;
import com.hyts.jgit.bean.RemoteOperateModel;
import com.hyts.jgit.config.GitParamConfiguration;
import lombok.Builder;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.PushCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.transport.PushResult;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.MessageFormat;

/**
 * project-name:coffice-toolbox
 * package-name:com.hyts.gitclient.handler
 * author:Libo/Alex
 * create-date:2019-06-14 21:30
 * copyright:libo-hyts-github
 * email:libo2dev@aliyun.com
 * description:此类主要用于: 远程服务的基础操作数据句柄处理器
 */
@Builder
@Slf4j
public class RemoteBaseHandler implements RemoteBaseSpi<RemoteOperateModel, ResultModel> {

    /**
     * clone 克隆文件服务
     * @param param
     * @return
     */
    @Override
    public ResultModel clone(RemoteOperateModel param) {
        log.info("克隆远程文件仓库URL:{} -> 本地文件仓库路径服务:{}",
                param.getRemoteModel().getRemoteRepositoryPath(),
                param.getLocalModel().getLocalRepositoryPath());
        try {
            Git.cloneRepository().
                        setBranch(param.getRemoteModel().getRemoteBranchName()).
                        setURI(param.getRemoteModel().getRemoteRepositoryPath()).
                        setDirectory(new File(param.getLocalModel().getLocalRepositoryPath())).call();
        } catch (GitAPIException e) {
            log.error("克隆远程仓库文件失败!",e);
            return ResultModel.failure(MessageFormat.format("克隆远程仓库文件失败:{0}",e));
        }
        return ResultModel.success("克隆远程仓库文件成功");
    }

    @Override
    public ResultModel fetch(RemoteOperateModel param) {
        return null;
    }

    /**
     * 拉取文件服务
     * @param param
     * @return
     */
    @Override
    public ResultModel pull(RemoteOperateModel param) {
        String path = param.getLocalModel().getLocalRepositoryPath();
        try {
            if(!path.endsWith(File.separator)){
                path+=File.separator;
            }
            File file = new File(path+ GitParamConfiguration.DEFAULT_GIT_REPOSITORY_PATH);
            if(!file.exists()){
                throw new FileNotFoundException("Git服务目录文件不存在!");
            }
            Git.open(file).pull().setRemote("orgin").setRemoteBranchName(param.getRemoteModel().getRemoteBranchName()).call();
        } catch (GitAPIException | IOException e) {
            log.error("拉取远程仓库代码文件!", e);
            return ResultModel.failure(MessageFormat.format("克隆远程仓库代码失败:{0}", e));
        }
        return ResultModel.success("拉取远程仓库文件成功");
    }

    /**
     * 推送文件服务
     * @param param
     * @return
     */
    @Override
    public ResultModel push(RemoteOperateModel param) {
        //认证服务对象
        if(param.getLocalModel().getAuthModel() == null ||
                param.getLocalModel().getAuthModel().getUsernamePasswordCredentialsProvider() == null){
            throw new IllegalStateException("无法访问，授权失败!");
        }
        StringBuilder stringBuilder = new StringBuilder();
        try {
            Git git = Git.open(new File(param.getLocalModel().getLocalRepositoryPath()));
            PushCommand pushCommand = git.push().setRemote("orgin");
            pushCommand.setCredentialsProvider(param.getLocalModel().getAuthModel().getUsernamePasswordCredentialsProvider());
            Iterable<PushResult> pushResults = pushCommand.setForce(param.isForce()).setPushTags().setPushAll().call();
            pushResults.forEach(attr->{
                stringBuilder.append(attr.getMessages()).append("\n");
            });
        } catch (IOException | GitAPIException e) {
           log.error("推送远程服务文件失败！",e);
            return ResultModel.failure(MessageFormat.format("推送远程仓库代码失败:{0}", e));
        }
        return ResultModel.success(String.format("推送远程仓库文件成功:{}",stringBuilder.toString()));
    }

    @Override
    public ResultModel reset(RemoteOperateModel param) {
        return null;
    }
}
